package de.dhbw.karlsruhe.picsim.model.commands.impl;

import de.dhbw.karlsruhe.picsim.model.actions.ActionFactory;
import de.dhbw.karlsruhe.picsim.model.actions.PicAction;
import de.dhbw.karlsruhe.picsim.model.commands.PicInstruction;
import de.dhbw.karlsruhe.picsim.model.cpu.PicInstructionFacade;
import de.dhbw.karlsruhe.picsim.model.cpu.ReadOnlyFile;
import de.dhbw.karlsruhe.picsim.model.memory.RegisterValue;
import de.dhbw.karlsruhe.picsim.util.Bits;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 13, 2010
 * Time: 8:21:54 PM
 */

/**
 * Entscheidet ob ins w oder ins adressierte register geschrieben wird
 * Klassen die hiervon erben müsssen nur noch den neuen Wert bestimmen
 */
abstract class InstructionSupport implements PicInstruction {
    private static final Log log = LogFactory.getLog(InstructionSupport.class);
    private final boolean targetIsWRegister;
    private final Bits argument;
    private final boolean influenceZero;


    InstructionSupport(final boolean targetIsWRegister, final boolean influenceZero, final Bits argument) {
        this.influenceZero = influenceZero;
        if (argument.getLength() != 7) {
            throw new IllegalArgumentException("argument.getLength()=" + argument.getLength());
        }
        this.targetIsWRegister = targetIsWRegister;
        this.argument = argument;
    }

    @NotNull
    @Override
    public final List<? extends PicAction> getActions(@NotNull final PicInstructionFacade pic) {
        log.debug("a command is executed, its target will be " + (targetIsWRegister ? "WRegister" : "a file"));
        final List<PicAction> result = new ArrayList<PicAction>();

        final ReadOnlyFile addressedFile = pic.getFor7BitAddress(argument);
        final List<PicAction> specificActions = new ArrayList<PicAction>();
        final RegisterValue value = getValue(addressedFile.getData(), pic.getWRegister().getData(), specificActions,
                                             pic.getActionFactory());
        if (targetIsWRegister) {
            result.add(pic.getActionFactory().createWriteInWAction(value));
        } else {
            result.add(pic.getActionFactory().createWriteInFileAction(argument, value));
        }
        if (influenceZero) {
            if (value.asInteger() == 0) {
                result.add(pic.getActionFactory().setZeroBit());
            } else {
                result.add(pic.getActionFactory().clearZeroBit());
            }
        }
        result.addAll(specificActions);
        return result;
    }


    @NotNull
    protected abstract RegisterValue getValue(@NotNull RegisterValue addressedFile, @NotNull RegisterValue wRegister,
                                              @NotNull List<PicAction> yourActions,
                                              @NotNull ActionFactory actionFactory);
}
